package com.ziroom.crm.mq.core.processor.retry;

import com.ziroom.crm.mq.core.config.MqConfig;
import com.ziroom.crm.mq.core.context.InvokeContext;
import com.ziroom.crm.mq.core.processor.QueueWrapper;
import com.ziroom.crm.mq.core.processor.ReSendProcessor;
import com.ziroom.crm.mq.core.retry.*;
import com.ziroom.crm.mq.core.spi.SpiLoader;
import com.ziroom.crm.mq.core.spi.SpiOrder;
import com.ziroom.crm.mq.core.util.AssertUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * <p>重试机制</p>
 * 重试的不是具体实现，而是reConsume,reSend 等
 * <p>
 * <PRE>
 * <BR>    修改记录
 * <BR>-----------------------------------------------
 * <BR>    修改日期         修改人          修改内容
 * </PRE>
 *
 * @author WeiShaoying
 * @version 1.0
 * @date Created in 2020年09月08日 10:06
 * @since 1.0
 */
@SpiOrder(SpiOrder.LOWEST_PRECEDENCE - 1)
@Slf4j
public class DefaultReSendRetryProcessor implements ReSendProcessor {

    public static final String GROUP_RESEND = "resend";

    private final RetryHandler retryHandler;


    public DefaultReSendRetryProcessor() {
        // spi 方式加载指定配置
        String retryPolicyName = MqConfig.getConfig(MqConfig.RETRY_RESEND_POLICY);
        String delayPolicyName = MqConfig.getConfig(MqConfig.RETRY_RESEND_DELAY_POLICY);
        log.info("retryPolicyName = " + retryPolicyName + ",delayPolicyName = " + delayPolicyName);

        RetryPolicy retryPolicy = SpiLoader.loadPrototypeInstanceByAlias(RetryPolicy.class, retryPolicyName, GROUP_RESEND);
        AssertUtil.notNull(retryPolicy, "RetryPolicy with alias[" + retryPolicyName + "] and group [" + GROUP_RESEND + "] must has one implement!");

        DelayPolicy delayPolicy = SpiLoader.loadPrototypeInstanceByAlias(DelayPolicy.class, delayPolicyName, GROUP_RESEND);
        AssertUtil.notNull(retryPolicy, "DelayPolicy with alias[" + delayPolicyName + "] and group [" + GROUP_RESEND + "] must has one implement!");

        retryHandler = new DefaultRetryHandler(retryPolicy, delayPolicy);
    }


    @Override
    public void postReSend(InvokeContext invokeContext, QueueWrapper queueWrapper) {
        Integer initRetryCount = invokeContext.getMessage().getRetryCount();
        // 持久化重试
        RetryContext retryContext = RetryContext.valueOf(invokeContext, RetryType.PERSISTENCE, initRetryCount);

        //持久化重试,不用执行重试方法，直接处理异常部分即可，仅有异常才会调用
        Exception exception = retryContext.getMessage().getException();
        if (Objects.nonNull(exception)) {
            retryHandler.handleException(retryContext, exception);
        }
    }

}
